
#include "loadlibraryproxy.h"
#include "makertype.h"

#ifdef LINUX
#include <limits.h>
#include <unistd.h>
#elif defined WINDOWS
#include <windows.h>
#else /* NIX */
#include <limits.h>
#define _PSTAT64
#include <sys/pstat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include <string.h>




CLoadLibraryProxy* CLoadLibraryProxy::pLoadLibraryProxy = NULL;
unsigned long CLoadLibraryProxy::CLoadLibraryProxyCounter  = 0;

CLoadLibraryProxy::CLoadLibraryProxy()
{
  dl_list.clear();
}

CLoadLibraryProxy::~CLoadLibraryProxy()
{
  if(pmoduleloader)
  {
     delete pmoduleloader;
     pmoduleloader = NULL;
  }
}


unsigned long CLoadLibraryProxy::DeleteLoadLibraryProxy()
{
  if(!(CLoadLibraryProxyCounter--))
  {
    CLoadLibraryProxyCounter = 0;
    delete this;
  }
  return CLoadLibraryProxyCounter;
}

bool CLoadLibraryProxy::IsCreatedLoadLibraryProxy()
{
   if(CLoadLibraryProxyCounter)
     return true;
   else
     return false;
}

void CLoadLibraryProxy::setModuleLoadLibrary( CModuleLoadLibrary * moduleloader)
{
  pmoduleloader = moduleloader;
}

CModuleLoadLibrary *CLoadLibraryProxy::getModuleLoadLibrary()
{
  return pmoduleloader;
}

void CLoadLibraryProxy::setBasePathLibrary(std:: string basepathlibrary)
{
  basepath = basepathlibrary;
}

std::string CLoadLibraryProxy::getBasePathLibrary()
{
  return basepath;
}

baseobject *CLoadLibraryProxy::findObject(std:: string snamespace, std::string sobjectname)
{
#ifdef _WIN_MSVS
  std::string   path             = basepath + "\\" + snamespace  + "\\" + sobjectname + ".dll";
#else
  std::string   path             = basepath + "/" + snamespace  + "/" + sobjectname + ".so";
#endif
  std::string   modulename       = snamespace + "_" + sobjectname + "_maker_t";
  void         *mkr              = NULL;
  maker_t       mkfunc           = NULL;
  baseobject  *loadedobj        = NULL;
  ObjectInfo    lObjectInfo;
  void *phandle                  = pmoduleloader->Open(path);
  
  if(phandle == NULL) return NULL;

  lObjectInfo.handle = phandle;
  lObjectInfo.name  = modulename;
  dl_list.insert(dl_list.end(), lObjectInfo);
  
  mkr = pmoduleloader->Load(phandle, modulename);
  if(mkr == NULL) return NULL;

  mkfunc = (maker_t)mkr;

  loadedobj = (*mkfunc)();
  return loadedobj;
}

void CLoadLibraryProxy::deleteObject(std:: string snamespace, std::string sobjectname)
{
  std::string                     modulename = snamespace + "_" + sobjectname + "_maker_t";
  std::list<ObjectInfo>::iterator dl_list_iterator;

  for(dl_list_iterator = dl_list.begin(); dl_list_iterator != dl_list.end(); dl_list_iterator ++)
  {
    if(dl_list_iterator->name.compare(modulename) == 0)
    {
      pmoduleloader->Close(dl_list_iterator->handle);
      dl_list.erase(dl_list_iterator);
      break;
    }
  }
}

std::string CLoadLibraryProxy::getexedir()
{
  std::string path = getexepath();
#if defined (__WIN32__)
  const char c = '\\';
#else
  const char c = '/';
#endif
  std::string::iterator it;

  for ( it = path.end() ; it > path.begin(); it-- )
  {
    if(*it == c) break;
  }

  path.erase(it, path.end());
  return path;
}

const char* CLoadLibraryProxy::get_directory( char* path )
{
#if defined (__WIN32__)
  const char c = "\\";
#else
  const char* c = "/";
#endif
  getcwd( path, 260 );
  strcat( path, c );
  return path;
}

std::string CLoadLibraryProxy::getexepath()
{
#ifdef LINUX

 char result[ PATH_MAX ];
 ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
 return std::string( result, (count > 0) ? count : 0 );

#elif defined WINDOWS

 char result[ MAX_PATH ];
 return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );

#else /* HP-UX */

  char result[ PATH_MAX ];
  struct pst_status ps;

  if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0)
    return std::string();

  if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0)
    return std::string();

  return std::string( result );

#endif
}



